#
# Documenation Generator Script.
# Enjoy this commented line, for it will be your last.
#

import os

Infos = {}
Bases = {}
FuncAvailability = {}

IMPLEMENTED = 0
NOT_IMPLEMENTED = 1
NOT_NEEDED = 2
MAYBE_NEEDED = 3
UNKNOWN = 4


szDocsDir = "docs"

def createInfos():

    szPolicyDir = os.path.join("..", "GerikSpellsDemo", "assets", "python", "GerikSpells", "Policies")

    global Infos
    global Bases
    global FuncAvailability

    for path, dirs, files in os.walk(szPolicyDir):
        if ".svn" in dirs:
            dirs.remove(".svn")

        for filename in files:
            szFullFilename = os.path.join(path, filename)
            f = open(szFullFilename, "r")
            
            bReadingClass = False
            bReadingDef = False
            bReadingModule = True
            bFindDocStart = True
            bFindDocEnd = False
            szClass = ""
            szDef = ""
            szDoc = ""

            szModuleName = filename.split(".")[0]
            Infos[szModuleName] = {}
            Infos[szModuleName]["doc"] = ""
            FuncAvailability[szModuleName] = {}
            
            for line in f.readlines():
                line = line.strip()
                if line.startswith("class"):
                    szClass = line.split("class")[1].strip().split("(")[0].replace(":", "")
                    Infos[szModuleName][szClass] = {}
                    Infos[szModuleName][szClass]["doc"] = ""
                    FuncAvailability[szModuleName][szClass] = {}
                    Infos[szModuleName][szClass]["inherits"] = []
                    if (szClass == "GSBase"):
                        Bases[szModuleName] = []

                    else:
                        parentClasses = line.split("(")[1].split(")")[0]
                        if (parentClasses.find(",") != -1):
                            for parentClass in line.split(","):
                                Infos[szModuleName][szClass]["inherits"].append(parentClass.strip())
                        else:
                            Infos[szModuleName][szClass]["inherits"].append(parentClasses.strip())
                    bFindDocStart = True
                    bFindDocEnd = False
                    bReadingClass = True
                    bReadingDef = False

                elif line.startswith("def"):
                    szDef = line.split("def")[1].strip().split(":")[0]
                    Infos[szModuleName][szClass][szDef] = ""
                    bFindDocStart = True
                    bFindDocEnd = False
                    bReadingDef = True
                    bReadingClass = False
                    if (szClass == "GSBase"):
                        Bases[szModuleName].append(szDef)

                elif line.startswith('"""'):
                    if (bFindDocStart):
                        bFindDocEnd = True
                        bFindDocStart = False
                    elif (bFindDocEnd):
                        if bReadingClass:
                            bReadingClass = False
                            bFindDocEnd = False
                            Infos[szModuleName][szClass]["doc"] = szDoc
                        elif bReadingDef:
                            bReadingDef = False
                            bFindDocEnd = False
                            Infos[szModuleName][szClass][szDef] = szDoc
                        elif bReadingModule:
                            bReadingModule = False
                            bFindDocEnd = False
                            Infos[szModuleName]["doc"] = szDoc

                        szDoc = ""

                elif line.startswith("<FuncImplemented>"):
                    FuncAvailability[szModuleName][szClass][szDef.split("(")[0]] = IMPLEMENTED
                elif line.startswith("<FuncNotImplemented>"):
                    FuncAvailability[szModuleName][szClass][szDef.split("(")[0]] = NOT_IMPLEMENTED
                elif line.startswith("<FuncNotNeeded>"):
                    FuncAvailability[szModuleName][szClass][szDef.split("(")[0]] = NOT_NEEDED
                elif line.startswith("FuncMaybeNeeded>"):
                    FuncAvailability[szModuleName][szClass][szDef.split("(")[0]] = MAYBE_NEEDED

                elif bFindDocEnd:
                    szDoc += "%s\n" % line

def createTopReference():
    pFile = open(os.path.join(szDocsDir, "TopReference.txt"), "w")
    pFile.write("! Policy References\n\n")
    for szModuleName in Infos:
        pFile.write("!! [%s]\n\n" % szModuleName)
        for szPolicyName in Infos[szModuleName]:
            if szPolicyName in ("doc","GSBase","inherits"):
                continue
            pFile.write("* [%s]\n" % szPolicyName)
        pFile.write("\n")

    pFile.close()

def makeFunctionString(szString):
    szName = szString.split("(")[0]
    szArgs = szString.split("(")[1].split(")")[0]
    pArgsList = []
    for arg in szArgs.split(","):
        pArgsList.append(arg.strip())
        
    szOutput = "<font color='#0000CC'>%s</font>" % szName
    szOutput += " ("
    bFirst = True
    for arg in pArgsList:
        if bFirst:
            szOutput += " <font color='#CC0000'>%s</font> " % arg
            bFirst = False
        else:
            szOutput += ", <font color='#CC0000'>%s</font> " % arg
    szOutput += ")"
    return szOutput

def makeFunctionDocString(szDocString):
    szString = ""
    lines = szDocString.split("\n")
    for line in lines:
        if (line.lower().startswith("arguments:")):
            szString += "\n**%s**\n" % line
        elif (line.lower().startswith("returns:")):
            szString += "\n**%s**\n" % line
        elif (line.lower().startswith("description:")):
            szString += "\n**%s**\n" % line
        elif (line.startswith("@")):
            if line.lower() == "@none":
                szString += "\n** ''None''\n"
            else:
                args, desc = line.split(":")
                args = args.replace("@", "", 1)
                szString += "\n** **%s**: %s" % (args, desc)
        elif (line.startswith(">")):
            szString += "\n** %s" % line.replace(">", "", 1)
        else:
            szString += "%s" % line
            
    return szString

def classFuncAvailability(szModule, szPolicy, szFunc):
    szFuncName = szFunc.split("(")[0]
    if (FuncAvailability[szModule][szPolicy].has_key(szFuncName)):
        return FuncAvailability[szModule][szPolicy][szFuncName]

    for szParentClass in Infos[szModule][szPolicy]["inherits"]:
        tempAvailability = classFuncAvailability(szModule, szParentClass, szFunc)
        if tempAvailability != UNKNOWN:
            return tempAvailability

    return UNKNOWN

def createModuleDocs():

    for szModuleName in Infos:
        pFile = open(os.path.join(szDocsDir, "%s.txt" % szModuleName), "w")
        pFile.write("! %s\n\n" % szModuleName)
        pFile.write("<toc>\n\n")

        pFile.write("!! Description\n")

        pFile.write(Infos[szModuleName]["doc"].strip().replace("\n", " "))

        pFile.write("\n\n---\n\n")

        pFile.write("!! Functions Used:\n")
        pFile.write("Either through a policy, the following functions should be overridden.\n\n")

        for szFuncName in Bases[szModuleName]:
            pFile.write("%s\n" % makeFunctionString(szFuncName))

        pFile.write("\n---\n")

        pFile.write("\n!! Pre-Defined Policies:\n\n")

        for szPolicyName in Infos[szModuleName]:
            if (szPolicyName in ("doc", "GSBase")):
                continue
            pFile.write("\n---\n")
            pFile.write("!!! [%s]\n" % szPolicyName)
            pFile.write("\n")
            pFile.write("**Description**:")
            pFile.write(Infos[szModuleName][szPolicyName]["doc"].strip().replace("\n", " "))
            pFile.write("\n\n")
            pFile.write("**Function Implementation Chart ([FunctionImplementationChart|What is this?])**:\n")

            pFile.write("|")
            baseFuncs = Bases[szModuleName]
            for baseFunc in baseFuncs:
                if baseFunc in ("doc","inherits"):
                    continue
                pFile.write("%s|" % baseFunc.split("(")[0])

            pFile.write("\n")
            pFile.write("|")
            for baseFunc in baseFuncs:
                availability = classFuncAvailability(szModuleName, szPolicyName, baseFunc)
                if availability == IMPLEMENTED:
                    pFile.write("<font color='#009900'>Implemented</font>|")
                elif availability == NOT_IMPLEMENTED:
                    pFile.write("<font color='#CC0000'>Needs Implementation</font>|")
                elif availability == NOT_NEEDED:
                    pFile.write("<font color='#009900'>Not Needed</font>|")
                elif availability == MAYBE_NEEDED:
                    pFile.write("<font color='#FFFF00'>May Need Implementation</font>|")
                elif availability == UNKNOWN:
                    pFile.write("Unknown|")

            pFile.write("\n")

        pFile.close()

def createPolicyDocs():
    for szModuleName in Infos:
        for szPolicyName in Infos[szModuleName]:
            if szPolicyName in ("doc","GSBase","inherits"):
                continue

            pFile = open(os.path.join(szDocsDir, "%s.txt" % szPolicyName), "w")

            pFile.write("! %s\n\n" % szPolicyName)
            pFile.write("A member of [%s]" % szModuleName)
            pFile.write("<toc>\n\n")
            pFile.write("!! Description\n")
            pFile.write(Infos[szModuleName][szPolicyName]["doc"].strip().replace("\n", " "))
            pFile.write("\n\n---\n\n")

            pFile.write("**Function Implementation Chart ([FunctionImplementationChart|What is this?])**:\n")
            pFile.write("|")
            baseFuncs = Bases[szModuleName]
            for baseFunc in baseFuncs:
                if baseFunc in ("doc","inherits"):
                    continue
                pFile.write("%s|" % baseFunc.split("(")[0])

            pFile.write("\n")
            pFile.write("|")
            for baseFunc in baseFuncs:
                availability = classFuncAvailability(szModuleName, szPolicyName, baseFunc)
                if availability == IMPLEMENTED:
                    pFile.write("<font color='#009900'>Implemented</font>|")
                elif availability == NOT_IMPLEMENTED:
                    pFile.write("<font color='#CC0000'>Needs Implementation</font>|")
                elif availability == NOT_NEEDED:
                    pFile.write("<font color='#009900'>Not Needed</font>|")
                elif availability == UNKNOWN:
                    pFile.write("Unknown|")

            pFile.write("\n\n---\n\n")
            
            pFile.write("!! Functions Defined:\n\n")

            for szFuncName in Infos[szModuleName][szPolicyName]:
                if (szFuncName.startswith("__init__")):
                    pFile.write("!!! %s\n" % makeFunctionString(szFuncName))
                    pFile.write("%s\n \n \n \n \n" % makeFunctionDocString(Infos[szModuleName][szPolicyName][szFuncName]))

            funcNames = Infos[szModuleName][szPolicyName].keys()
            funcNames.sort()
            for szFuncName in funcNames:
                if (szFuncName in ("doc", "inherits") or szFuncName.startswith("__init__")):
                    continue
                pFile.write("---\n")
                pFile.write("!!! %s\n" % makeFunctionString(szFuncName))
                pFile.write("%s\n \n \n \n \n" % makeFunctionDocString(Infos[szModuleName][szPolicyName][szFuncName]))

            pFile.close()
            

if __name__=="__main__":
    createInfos()
    createTopReference()
    createModuleDocs()
    createPolicyDocs()
